/*
 * @Description: vue-cli4配置
 * @Author: wangqi
 * @Date: 2021-04-04 09:27:11
 * @LastEditTime: 2021-04-15 23:59:18
 */
const path = require('path')
const webpack = require("webpack")
const resolve = dir => path.resolve(dir)
// 预渲染
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;

// 去除多余无效的 css
const glob = require('glob')
const PurgeCSSPlugin = require('purgecss-webpack-plugin')

// 只打包改变的文件
const { HashedModuleIdsPlugin } = require('webpack')

// 开启 gzip 压缩
const CompressionWebpackPlugin = require("compression-webpack-plugin")
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;

// 打包分析
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin

// dll包引入
const addAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')

// cdn外链
const cdn = {
    // 访问https://unpkg.com/element-ui/lib/theme-chalk/index.css获取最新版本
    css: [
        "//unpkg.com/element-ui@2.10.1/lib/theme-chalk/index.css",
        "//unpkg.com/ant-design-vue@1.7.4/dist/antd.min.css",
    ],
    js: [
        "//unpkg.com/vue@2.6.10/dist/vue.min.js", // 访问https://unpkg.com/vue/dist/vue.min.js获取最新版本
        "//unpkg.com/vue-router@3.0.6/dist/vue-router.min.js",
        "//unpkg.com/vuex@3.1.1/dist/vuex.min.js",
        "//unpkg.com/axios@0.19.0/dist/axios.min.js",
        "//unpkg.com/element-ui@2.10.1/lib/index.js",
        "//cdn.bootcdn.net/ajax/libs/moment.js/2.29.1/moment.min.js",
        "//cdn.bootcdn.net/ajax/libs/moment.js/2.29.1/locale/zh-cn.min.js",
        "//unpkg.com/ant-design-vue@1.7.4/dist/antd.min.js",
    ]
};
const externals = {
    "vue": "Vue",
    "element-ui": "ELEMENT",
    "vue-router": "VueRouter",
    "vuex": "Vuex",
    "axios": "axios",
    "moment": "moment",
    "ant-design-vue": "antd",
};

const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV);


module.exports = {
    publicPath: process.env.VUE_APP_PUBLIC_PATH, //IS_PROD ? process.env.VUE_APP_PUBLIC_PATH : "./", // 默认'/'，部署应用包时的基本 URL
    lintOnSave: false, //是否在保存的时候使用 `eslint-loader` 进行检查。
    runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
    productionSourceMap: !IS_PROD, // 生产环境的 source map

    css: {
        // 向全局sass样式传入共享的全局变量
        loaderOptions: {
            scss: { prependData: `@import "~@/assets/css/index.scss";` }
        },
    },

    chainWebpack: config => {
        // 别名
        config.resolve.alias
            .set("vue$", "vue/dist/vue.esm.js")
            .set("@", resolve("src"));

        // 使用 SVG 组件
        const svgRule = config.module.rule("svg");
        svgRule.uses.clear();
        svgRule.exclude.add(/node_modules/);
        svgRule.test(/\.svg$/).use("svg-sprite-loader").loader("svg-sprite-loader").options({ symbolId: "icon-[name]" });
        const imagesRule = config.module.rule("images");
        imagesRule.exclude.add(resolve("src/icons"));
        config.module.rule("images").test(/\.(png|jpe?g|gif|svg)(\?.*)?$/);

        // 删除开发环境中 moment 语言包
        config.plugin("ignore").use(new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn$/));
        if (IS_PROD) {
            // 压缩图片
            // config.module
            //     .rule('images')
            //     .use("image-webpack-loader")
            //     .loader("image-webpack-loader")
            //     .options({
            //         mozjpeg: { progressive: true, quality: 65 },
            //         optipng: { enabled: false },
            //         pngquant: { quality: [0.65, 0.9], speed: 4 },
            //         gifsicle: { interlaced: false }
            //         // webp: { quality: 75 }
            //     });

            config.optimization.delete("splitChunks");
            // 打包分析
            config.plugin("webpack-report").use(BundleAnalyzerPlugin, [{ analyzerMode: "static" }]);
        }

        return config;
    },

    configureWebpack: config => {
        const plugins = [];
        if (IS_PROD) {
            // 预渲染
            let prerenderspaplugin = new PrerenderSPAPlugin({
                staticDir: resolve('dist'), // 读取vue-cli已打包文件的根目录 prerender-spa-plugin会在这里开启一个服务
                // 根据项目的输出目录outputDir,和入口文件配置
                // outputDir: path.join(__dirname, '/dist'), 
                // indexPath: path.join(__dirname, 'dist/index.html'), // 指定入口html
                routes: ['/', '/about'], // 哪些路由页面需要预渲染
                minify: {
                    minifyCSS: true, // css压缩
                    removeComments: true, // 移除注释
                    collapseBooleanAttributes: true,
                    collapseWhitespace: true,
                    decodeEntities: true,
                    keepClosingSlash: true,
                    sortAttributes: true
                },
                renderer: new Renderer({
                    // 需要注入一个值，这样就可以检测页面当前是否是预渲染的
                    inject: {
                        foo: 'bar'
                    },
                    headless: false,
                    // 视图组件是在API请求获取所有必要数据后呈现的，因此我们在dom中存在“data view”属性后创建页面快照
                    renderAfterDocumentEvent: 'render-event',
                    args: ['--no-sandbox', '--disable-setuid-sandbox']
                })
            });

            // 去除多余无效的 css
            let purgecssplugin = new PurgeCSSPlugin({
                paths: glob.sync(`${resolve('src')}/**/*.vue`, { nodir: true }),
                // 配置白名单
                whitelist: ["html", "body"],
                whitelistPatterns: [/el-.*/],
                whitelistPatternsChildren: [/^token/, /^pre/, /^code/]
            });

            // 开启 gzip 压缩
            let compressionwebpackplugin = new CompressionWebpackPlugin({
                filename: "[path].gz[query]",
                algorithm: "gzip",
                test: productionGzipExtensions,
                threshold: 10240,
                minRatio: 0.8
            });

            // 只打包改变的文件
            let hashedmoduleidsplugin = new HashedModuleIdsPlugin();

            // cdn外链 -- [打包忽略文件]
            config.externals = externals;

            config.optimization = {
                splitChunks: {
                    cacheGroups: {
                        common: {
                            name: "chunk-common",
                            chunks: "initial",
                            minChunks: 2,
                            maxInitialRequests: 5,
                            minSize: 0,
                            priority: 1,
                            reuseExistingChunk: true,
                            enforce: true
                        },
                        vendors: {
                            name: "chunk-vendors",
                            test: /[\\/]node_modules[\\/]/,
                            chunks: "initial",
                            priority: 2,
                            reuseExistingChunk: true,
                            enforce: true
                        }
                    }
                }
            }

            plugins.push(/**prerenderspaplugin,*/ purgecssplugin, compressionwebpackplugin, hashedmoduleidsplugin);
        }
        // dll动态链接库配置
        let dllreferenceplugin = new webpack.DllReferencePlugin({           
            manifest: path.join(__dirname, './dll/vendor-manifest.json'),
        });
        // 将动态链接库放到index页面
        let addassethtmlwebpackplugin = new addAssetHtmlWebpackPlugin({
            filepath: path.join(__dirname, './dll/jquery.js'),
        });

        plugins.push(dllreferenceplugin, addassethtmlwebpackplugin);

        config.plugins = [...config.plugins, ...plugins];
    },

    pages: {
        //入口页面配置
        index: {
            entry: 'src/main.js',
            template: 'public/index.html',
            // 在 dist/index.html 的输出
            filename: 'index.html',
            cdn: IS_PROD ? cdn : null,
            chunks: ['chunk-vendors', 'chunk-common', 'index'],
            title: "测试vue cdn"
        },
    }

};
